#include "string.h"
using namespace bit;

const int string::npos = -1;

string::string(const char* str)
	:_size(strlen(str))
{
	_capacity = _size;
	_str = new char[_capacity + 1];
	strcpy(_str, str);
}

string::string(const string& s)
{
	_str = new char[s._capacity + 1];
	strcpy(_str, s._str);
	_size = s._size;
	_capacity = s._capacity;
}

string::~string()
{
	delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}

iterator string::begin()const
{
	return _str;
}

iterator string::end()const
{
	return _str + _size;
}

string& string::operator=(const string& s)
{
	char* tmp = new char[s._capacity + 1];
	strcpy(tmp, s._str);
	delete[] _str;
	_str = tmp;
	_size = s._size;
	_capacity = s._capacity;
	return *this;
}

void string::push_back(char c)
{
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}
	_str[_size] = c;
	++_size;
	_str[_size] = '\0';
}

string& string::operator+=(char c)
{
	push_back(c);
	return *this;
}

void string::append(const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
	strcpy(_str + _size, str);
	_size = _size + len;
}

string& string::operator+=(const char* str)
{
	append(str);
	return *this;
}

void string::clear()
{
	_size = 0;
	_str[_size] = '/0';
}

void string::swap(string& s)
{
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

const char* string::c_str()const
{
	return _str;
}

size_t string::size()const
{
	return _size;
}

size_t string::capacity()const
{
	return _capacity;
}

bool string::empty()const
{
	return !_size;
}

void string::resize(size_t n, char c)
{
	if (n > _size)
	{
		reserve(n);
		for (int i = _size; i < n; i++)
		{
			_str[i] = c;
		}
		_str[n] = '\0';
		_size = n;
	}
	else
	{
		_str[n] = '\0';
		_size = n;
	}
}

char& string::operator[](size_t index)
{
	assert(index < _size);
	return _str[index];
}

const char& string::operator[](size_t index)const
{
	assert(index < _size);
	return _str[index];
}

bool string::operator<(const string& s)
{
	int ret = strcmp(_str, s._str);
	return ret < 0;
}

bool string::operator<=(const string& s)
{
	return _str < s._str || _str == s._str;
}

bool string::operator>(const string& s)
{
	return !(_str <= s._str);
}

bool string::operator>=(const string& s)
{
	return !(_str < s._str);
}

size_t string::find(char c, size_t pos) const
{
	assert(pos < _size);
	for (size_t i = pos; i < _size; i++)
	{
		if (_str[i] == c)
		{
			return i;
		}
	}
	return npos;
}

size_t string::find(const char* s, size_t pos) const
{
	assert(pos < _size);
	const char* p = strstr(_str + pos, s);
	if (p)
	{
		return p - _str;
	}
	else
	{
		return npos;
	}
}

void string::insert(size_t pos, char c)
{
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}
	size_t end = _size + 1;
	while (end > pos)
	{
		_str[end] = _str[end - 1];
		--end;
	}
	_str[pos] = c;
	_size++;
}

void string::insert(size_t pos, const char* str)
{
	assert(pos < _size);
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
	size_t end = _size + len;
	while (end > pos + len - 1)
	{
		_str[end] = _str[end - len];
		--end;
	}
	strcpy(_str + pos, str);
	_size = _size + len;
}

void string::erase(size_t pos, size_t n)
{
	assert(pos < _size);
	if (n >= _size - pos)
	{
		_str[pos] = '\0';
		_size = pos;
	}
	else
	{
		strcpy(_str + pos, _str + pos + n);
		_size = _size - n;
	}
}


bool string::operator==(const string& s)
{
	int ret = strcmp(_str, s._str);
	return ret == 0;
}

bool string::operator!=(const string& s)
{
	return !(*this == s);
}


void string::reserve(size_t n)
{
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}


std::ostream& bit::operator<<(std::ostream& _cout, const string& s)
{
	for (auto ch : s)
	{
		_cout << ch;
	}
	return _cout;
}

std::istream& bit::operator>>(std::istream& _cin, string& s)
{
	s.clear();
	char ch;
	ch = _cin.get();
	char buff[128];
	size_t i = 0;
	while (ch != ' ' && ch != '\n')
	{
		buff[i] = ch;
		i++;
		if (i == 127)
		{
			buff[127] = '\0';
			s += buff;
			i = 0;
		}
		ch = _cin.get();
	}
	if (i > 0)
	{
		buff[i] = '\0';
		s += buff;
	}
	return _cin;
}
